package cn.com.headfree.base.initdata;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.web.context.WebApplicationContext;

import com.gta.edu.sdk.config.DateJsonValueProcessor;
import com.gta.edu.sdk.config.DateMorpher;
import com.gta.edu.sdk.util.EhCacheUtil;
import com.gta.edu.sdk.util.RedisClusterUtil;
import com.gta.edu.sdk.util.SpringContextHolder;
import com.gta.edu.sdk.util.StringUtil;

import cn.com.headfree.base.config.DictConfig;
import cn.com.headfree.dictionary.entity.TCommonDictionary;
import cn.com.headfree.dictionary.service.IDictionaryService;
import net.sf.json.JSONArray;
import net.sf.json.JsonConfig;
import net.sf.json.util.JSONUtils;

/**
 * Title:系统启动时，初始化数据 Description: Copyright: Copyright (c) 2017 Company:
 * www.headfree.com.cn
 * 
 * @author fengya
 * @version 1.0
 * @date 2019年7月8日 下午5:04:46
 */
public class InitCacheData {
	private static InitCacheData instance;

	private static final Logger LOG = LogManager.getLogger(InitCacheData.class);

	public static final String ROOT = "root";

	private DictConfig config;

	private JsonConfig cfg;

	private InitCacheData() {
		this.config = SpringContextHolder.getBean(DictConfig.class);
		this.cfg = new JsonConfig();
		this.cfg.registerJsonValueProcessor(Date.class, new DateJsonValueProcessor());
	}

	public static InitCacheData getInstance() {
		synchronized (InitCacheData.class) {
			if (instance == null) {
				instance = new InitCacheData();
			}
			return instance;
		}
	}

	/**
	 * @description 系统启动加载初始项
	 * @author fengya
	 * @date 2017年5月22日 下午5:28:28
	 * @throws @return void
	 */
	public void initData(WebApplicationContext app) {
		LOG.info("************初始化数据字典数据开始******************");
		try {
			initDictionaryData(app);
		} catch (Exception e) {
			LOG.info("************初始化数据字典数据失败******************", e);
		}
		LOG.info("************初始化数据字典数据结束******************");
	}

	/**
	 * @description 初始化数据字典信息
	 * @author 冯亚
	 * @date 2019年7月8日 下午5:33:59
	 * @param app
	 * @return void
	 */
	public String initDictionaryData(WebApplicationContext app) {
		IDictionaryService dictService = (IDictionaryService) app.getBean("dictionaryService");
		List<TCommonDictionary> dictAll = dictService.findAll();
		String redisData = null;
		if (dictAll != null && dictAll.size() > 0) {
			redisData = JSONArray.fromObject(dictAll, this.cfg).toString();
			EhCacheUtil.put(this.config.getRedisDictionaryKey(), redisData);
			RedisClusterUtil.getInstance().setString(this.config.getRedisDictionaryKey(), redisData,this.config.getRedisDictionaryTimeLong());
		}
		return redisData;
	}

	/**
	 * @description 把数据字典根据系统编码进行分组
	 * @author 冯亚
	 * @date 2019年7月10日 下午2:59:42
	 * @param dictAll
	 * @return
	 * @return Map<String,List<TDictionary>>
	 */
	private Map<String, List<TCommonDictionary>> groupDictionary(List<TCommonDictionary> dictAll) {
		Map<String, List<TCommonDictionary>> dictMap = new HashMap<String, List<TCommonDictionary>>();
		for (TCommonDictionary dict : dictAll) {
			if (!StringUtil.isNullOrEmpty(dict.getSysCode())) {
				if (!dictMap.containsKey(dict.getSysCode())) {
					dictMap.put(dict.getSysCode(), new ArrayList<TCommonDictionary>());
				}
				dictMap.get(dict.getSysCode()).add(dict);
			}
		}
		return dictMap;
	}

	/**
	 * @description 递归调用，把数据字典的数据构造出一个树形结构的数据，放入到Data中。
	 * @author 冯亚
	 * @date 2019年7月8日 下午5:40:16
	 * @param pId
	 * @param dictList
	 * @return void
	 */
	private void writeData(TCommonDictionary pdict, List<TCommonDictionary> dictList,
			Map<String, List<TCommonDictionary>> dictData) {
		for (TCommonDictionary dict : dictList) {
			if (pdict.getId().equals(dict.getpId())) {
				if (!dictData.containsKey(pdict.getValue())) {
					dictData.put(pdict.getValue(), new ArrayList<TCommonDictionary>());
				}
				dictData.get(pdict.getValue()).add(dict);
				this.writeData(dict, dictList, dictData);
			}
		}
	}

	/**
	 * @description 根据父节点的值，或者所有子节点的记录数据
	 * @author 冯亚
	 * @date 2019年7月10日 上午11:02:25
	 * @param parentValue
	 * @return
	 * @return List<TProjectDictionary>
	 */
	public List<TCommonDictionary> findDictionaryByParentValue(String sysCode, String parentValue,WebApplicationContext app) throws Exception {
		String redisData = EhCacheUtil.getValue(this.config.getRedisDictionaryKey());
		if (StringUtil.isNullOrEmpty(redisData)) {
			redisData = RedisClusterUtil.getInstance().getString(this.config.getRedisDictionaryKey());
			if (StringUtil.isNullOrEmpty(redisData)) {
				redisData = this.initDictionaryData(app);
				if (StringUtil.isNullOrEmpty(redisData)) {
					throw new Exception("初始化数据字典数据出现了异常，请与管理员联系！");
				}
			} else {
				EhCacheUtil.put(this.config.getRedisDictionaryKey(), redisData);
			}
		}

		Map<String, Map<String, List<TCommonDictionary>>> data = this.getDictData(redisData);
		Map<String, List<TCommonDictionary>> sysMap = data.get(sysCode);
		if (sysMap != null) {
			return sysMap.get(parentValue);
		}
		return null;
	}

	/**
	 * @description 根据父节点值和子节点的值，或者该子节点记录
	 * @author 冯亚
	 * @date 2019年7月10日 上午11:02:45
	 * @param parentValue
	 * @param value
	 * @return
	 * @return TProjectDictionary
	 * @throws Exception 
	 */
	public TCommonDictionary getDictionaryByParentValueAndValue(String sysCode, String parentValue, String value,WebApplicationContext app) throws Exception {
		List<TCommonDictionary> list = this.findDictionaryByParentValue(sysCode, parentValue, app);
		if (list != null) {
            for (TCommonDictionary dict : list) {
                if (dict.getValue().equals(value)) {
                    return dict;
                }
            }
        }
		return null;
	}

	/**
	 * @description 
	 * @author 冯亚
	 * @date 2020年6月4日 上午11:25:06
	 * @param redisData
	 * @return
	 * @return Map<String,Map<String,List<TCommonDictionary>>>
	 */
	private Map<String, Map<String, List<TCommonDictionary>>> getDictData(String redisData) {
		Map<String, Map<String, List<TCommonDictionary>>> data = new HashMap<String, Map<String, List<TCommonDictionary>>>();
		JSONArray array = JSONArray.fromObject(redisData);
		this.cfg.setRootClass(TCommonDictionary.class);
		JSONUtils.getMorpherRegistry().registerMorpher(new DateMorpher("yyyy-MM-dd HH:mm:ss"));
		List<TCommonDictionary> list = JSONArray.toList(array, this.cfg);
		TCommonDictionary pdict = null;
		for (TCommonDictionary dict : list) {
			if (ROOT.equals(dict.getpId())) {
				pdict = dict;
			}
		}
		Map<String, List<TCommonDictionary>> dictMap = this.groupDictionary(list);
		Entry<String, List<TCommonDictionary>> entry = null;
		Iterator<Entry<String, List<TCommonDictionary>>> it = dictMap.entrySet().iterator();
		Map<String, List<TCommonDictionary>> dictData = null;
		while (it.hasNext()) {
			entry = it.next();
			dictData = new HashMap<String, List<TCommonDictionary>>();
			this.writeData(pdict, entry.getValue(), dictData);
			data.put(entry.getKey(), dictData);
		}
		return data;
	}

}
